---
sidebar_label: Permissions
sidebar_position: 8
description: Manage permissions with the Hasura Metadata API
keywords:
  - hasura
  - docs
  - Metadata API
  - API reference
  - permission
---

# Metadata API Reference: Permissions

## Introduction

The permission layer is designed to restrict the operations that can be
performed by various users. Permissions can be defined on various
operations (insert/select/update/delete) at a role level granularity. By
default, the `admin` role has unrestricted access to all operations.

:::info Variables in rules

All `X-Hasura-*` header values can be used in the permission rules.
These values can come with the request and can be validated using
webhook or can be sent with the JWT token.

:::

:::tip Supported from

The Metadata API is supported for versions `v2.0.0` and above and
replaces the older [schema/Metadata API](/api-reference/schema-metadata-api/index.mdx).

:::

## pg_create_insert_permission {#metadata-pg-create-insert-permission}

An insert permission is used to enforce constraints on the data that is being inserted.

Let's look at an example, a permission for the `user` role to insert
into the `article` table. What is the constraint that we would like to
enforce here? _A user can only insert articles for themselves_ .

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "check" : {
                "author_id" : "X-HASURA-USER-ID"
            },
            "set":{
                "id":"X-HASURA-USER-ID"
            },
            "columns":["name","author_id"],
            "validate_input": {
                "type": "http",
                "definition": {
                "forward_client_headers": true,
                "headers": [],
                "timeout": 10,
                "url": "http://www.somedomain.com/validateUser"
                }
            }
        }
    }
}
```

This reads as follows - for the `user` role:

- For every row that is being inserted into the _article_ table, allow
  insert only if the `check` passes i.e. that the `author_id` column
  value is the same as the value in the request header
  `X-HASURA-USER-ID`".
- If the above `check` passes, then access for insert will be limited
  to columns `name` and `author_id` only.
- When this insert happens, the value of the column `id` will be
  automatically `set` to the value of the resolved session variable
  `X-HASURA-USER-ID`.

The argument for `check` is a boolean expression which has the same
syntax as the `where` clause in the `select` query, making it extremely
expressive.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "check" : {
                "author_id" : "X-HASURA-USER-ID",
                "$or" : [
                    {
                        "category" : "editorial",
                        "is_reviewed" : false
                    },
                    {
                        "category" : { "$neq" : "editorial"}
                    }
                ]
            }
        }
    }
}
```

In the above definition, the row is allowed to be inserted if the
`author_id` is the same as the request's user id and `is_reviewed` is
`false` when the `category` is "editorial".

### Args syntax {#metadata-pg-create-insert-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [InsertPermission](/api-reference/syntax-defs.mdx#insertpermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## pg_drop_insert_permission {#metadata-pg-drop-insert-permission}

The `pg_drop_insert_permission` API is used to drop an existing insert
permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_drop_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user"
    }
}
```

### Args syntax {#metadata-pg-drop-insert-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## pg_create_select_permission {#metadata-pg-create-select-permission}

A select permission is used to restrict access to only the specified columns and rows.

Let's look at an example, a permission for the `user` role to select
from the `article` table: all columns can be read, as well as the rows
that have been published or authored by the user themselves.

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_select_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default",
        "permission" : {
            "columns" : "*",
            "filter" : {
                "$or" : [
                    { "author_id" : "X-HASURA-USER-ID" },
                    { "is_published" : true }
                ]
             },
             "limit": 10,
             "allow_aggregations": true
        }
    }
}
```

This reads as follows - For the `user` role:

- Allow selecting rows where the `check` passes i.e. `is_published` is
  `true` or the `author_id` matches the value of the session variable
  `X-HASURA-USER-ID`.
- Allow selecting all columns (because the `columns` key is set to
  `*`).
- `limit` the numbers of rows returned by a query to the `article`
  table by the `user` role to a maximum of 10.
- Allow aggregate queries.
- All query and subscription root fields are enabled.

Let's take another example to show how to enable a particular set of
root fields.

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_select_permission",
    "args" : {
        "table" : "article",
        "role" : "guest",
        "source": "default",
        "permission" : {
            "columns" : "*",
            "filter" : {},
            "query_root_fields": ["select_by_pk"],
            "subscription_root_fields": ["select_by_pk"]

        }
    }
}
```

This reads as follows - for the `guest` role:

- Allow access to all the rows.
- Allow selecting all the columns.
- Allow only the `select_by_pk` root field in the `query` and `subscription` root fields. The
  other root fields will be disabled.

The select permission of the `guest` role is configured in a way such that, it can:

1. The access to the `article` table is restricted to what can be accessed through relationships to the `article` table.
2. If the `guest` has the access to the primary key value, it can access the data corresponding to that primary key.

### Args syntax {#metadata-pg-create-select-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [SelectPermission](/api-reference/syntax-defs.mdx#selectpermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## pg_drop_select_permission {#metadata-pg-drop-select-permission}

The `pg_drop_select_permission` is used to drop an existing select
permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_drop_select_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default"
    }
}
```

### Args syntax {#metadata-pg-drop-select-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## pg_create_update_permission {#metadata-pg-create-update-permission}

An update permission is used to restrict the columns and rows that can
be updated. Its structure is quite similar to the select permission.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_update_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "columns" : ["title", "content", "category"],
            "filter" : {
                "author_id" : "X-HASURA-USER-ID"
            },
            "check" : {
                "content" : {
                  "_ne": ""
                }
            },
            "set":{
                "updated_at" : "NOW()"
            },
            "validate_input": {
                "type": "http",
                "definition": {
                "forward_client_headers": true,
                "headers": [],
                "timeout": 10,
                "url": "http://www.somedomain.com/validateUser"
                }
            }
        }
    }
}
```

This reads as follows - for the `user` role:

- Allow updating only those rows where the `filter` passes i.e. the
  value of the `author_id` column of a row matches the value of the
  session variable `X-HASURA-USER-ID`.
- If the above `filter` passes for a given row, allow updating only
  the `title`, `content` and `category` columns (_as specified in the_
  `columns` _key_).
- After the update happens, verify that the `check` condition holds
  for the updated row i.e. that the value in the `content` column is
  not empty.
- When this update happens, the value of the column `updated_at` will
  be automatically `set` to the current timestamp.

:::info Note

It is important to deny updates to columns that will determine the row
ownership. In the above example, the `author_id` column determines the
ownership of a row in the `article` table. Columns such as this should
never be allowed to be updated.

:::

### Args syntax {#metadata-pg-create-update-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [UpdatePermission](/api-reference/syntax-defs.mdx#updatepermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## pg_drop_update_permission {#metadata-pg-drop-update-permission}

The `pg_drop_update_permission` API is used to drop an existing update
permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_drop_update_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user"
    }
}
```

### Args syntax {#metadata-pg-drop-update-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## pg_create_delete_permission {#metadata-pg-create-delete-permission}

A delete permission is used to restrict the rows that can be deleted.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_create_delete_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "filter" : {
                "author_id" : "X-HASURA-USER-ID"
            },
            "validate_input": {
                "type": "http",
                "definition": {
                "forward_client_headers": true,
                "headers": [],
                "timeout": 10,
                "url": "http://www.somedomain.com/validateUser"
                }
            }
        }
    }
}
```

This reads as follows:

"`delete` for the `user` role on the `article` table is allowed on rows
where `author_id` is the same as the request header `X-HASURA-USER-ID`
value."

### Args syntax {#metadata-pg-create-delete-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [DeletePermission](/api-reference/syntax-defs.mdx#deletepermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## pg_drop_delete_permission {#metadata-pg-drop-delete-permission}

The `pg_drop_delete_permission` API is used to drop an existing delete permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "pg_drop_delete_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default"
    }
}
```

### Args syntax {#metadata-pg-drop-delete-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## pg_set_permission_comment {#metadata-pg-set-permission-comment}

`pg_set_permission_comment` is used to set/update the comment on a permission. Setting the comment to `null` removes it.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: admin

{
    "type": "pg_set_permission_comment",
    "args": {
        "table": "article",
        "source": "default",
        "role": "user",
        "type" : "update",
        "comment" : "can only modify their own rows"
    }
}
```

### Args syntax {#metadata-pg-set-permission-comment-syntax}

| Key     | Required | Schema                                                  | Description                                                   |
| ------- | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table   | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role    | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | The role in the permission                                    |
| type    | true     | permission type (one of select/update/delete/insert)    | The type of the permission                                    |
| comment | false    | Text                                                    | Comment                                                       |
| source  | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## mssql_create_insert_permission {#mssql-create-insert-permission}

An insert permission is used to enforce constraints on the data that is being inserted.

Let's look at an example, a permission for the `user` role to insert
into the `article` table. What is the constraint that we would like to
enforce here? _A user can only insert articles for themselves_ .

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "check" : {
                "author_id" : "X-HASURA-USER-ID"
            },
            "set":{
                "id":"X-HASURA-USER-ID"
            },
            "columns":["name","author_id"]
        }
    }
}
```

This reads as follows - for the `user` role:

- For every row that is being inserted into the _article_ table, allow
  insert only if the `check` passes i.e. that the `author_id` column
  value is the same as the value in the request header
  `X-HASURA-USER-ID`".
- If the above `check` passes, then access for insert will be limited
  to columns `name` and `author_id` only.
- When this insert happens, the value of the column `id` will be
  automatically `set` to the value of the resolved session variable
  `X-HASURA-USER-ID`.

The argument for `check` is a boolean expression which has the same
syntax as the `where` clause in the `select` query, making it extremely
expressive.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "check" : {
                "author_id" : "X-HASURA-USER-ID",
                "$or" : [
                    {
                        "category" : "editorial",
                        "is_reviewed" : false
                    },
                    {
                        "category" : { "$neq" : "editorial"}
                    }
                ]
            }
        }
    }
}
```

In the above definition, the row is allowed to be inserted if the
`author_id` is the same as the request's user id and `is_reviewed` is
`false` when the `category` is "editorial".

### Args syntax {#mssql-create-insert-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [InsertPermission](/api-reference/syntax-defs.mdx#insertpermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## mssql_drop_insert_permission {#mssql-drop-insert-permission}

The `mssql_drop_insert_permission` API is used to drop an existing insert permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_drop_insert_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user"
    }
}
```

### Args syntax {#mssql-drop-insert-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## mssql_create_select_permission {#mssql-create-select-permission}

A select permission is used to restrict access to only the specified
columns and rows.

Let's look at an example, a permission for the `user` role to select
from the `article` table: all columns can be read, as well as the rows
that have been published or authored by the user themselves.

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_select_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default",
        "permission" : {
            "columns" : "*",
            "filter" : {
                "$or" : [
                    { "author_id" : "X-HASURA-USER-ID" },
                    { "is_published" : true }
                ]
             },
             "limit": 10,
             "allow_aggregations": true
        }
    }
}
```

This reads as follows - For the `user` role:

- Allow selecting rows where the `check` passes i.e. `is_published` is
  `true` or the `author_id` matches the value of the session variable
  `X-HASURA-USER-ID`.
- Allow selecting all columns (because the `columns` key is set to
  `*`).
- `limit` the numbers of rows returned by a query to the `article`
  table by the `user` role to a maximum of 10.
- Allow aggregate queries.
- All query and subscription root fields are enabled.

Let's take another example to show how to enable a particular set of
root fields.

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_select_permission",
    "args" : {
        "table" : "article",
        "role" : "guest",
        "source": "default",
        "permission" : {
            "columns" : "*",
            "filter" : {},
            "query_root_fields": ["select_by_pk"],
            "subscription_root_fields": ["select_by_pk"]

        }
    }
}
```

This reads as follows - for the `guest` role:

- Allow access to all the rows.
- Allow selecting all the columns.
- Allow only the `select_by_pk` root field in the `query` and `subscription` root fields. The
  other root fields will be disabled.

The select permission of the `guest` role is configured in a way such that, it can:

1. The access to the `article` table is restricted to what can be accessed through relationships to the `article` table.
2. If the `guest` has the access to the primary key value, it can access the data corresponding to that primary key.

### Args syntax {#mssql-create-select-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [SelectPermission](/api-reference/syntax-defs.mdx#selectpermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## mssql_drop_select_permission {#mssql-drop-select-permission}

The `mssql_drop_select_permission` is used to drop an existing select permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_drop_select_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default"
    }
}
```

### Args syntax {#mssql-drop-select-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## mssql_create_update_permission {#mssql-create-update-permission}

An update permission is used to restrict the columns and rows that can
be updated. Its structure is quite similar to the select permission.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_update_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "columns" : ["title", "content", "category"],
            "filter" : {
                "author_id" : "X-HASURA-USER-ID"
            },
            "check" : {
                "content" : {
                  "_ne": ""
                }
            },
            "set":{
                "updated_at" : "NOW()"
            }
        }
    }
}
```

This reads as follows - for the `user` role:

- Allow updating only those rows where the `filter` passes i.e. the
  value of the `author_id` column of a row matches the value of the
  session variable `X-HASURA-USER-ID`.
- If the above `filter` passes for a given row, allow updating only
  the `title`, `content` and `category` columns (_as specified in the_
  `columns` _key_).
- After the update happens, verify that the `check` condition holds
  for the updated row i.e. that the value in the `content` column is
  not empty.
- When this update happens, the value of the column `updated_at` will
  be automatically `set` to the current timestamp.

:::info Note

It is important to deny updates to columns that will determine the row
ownership. In the above example, the `author_id` column determines the
ownership of a row in the `article` table. Columns such as this should
never be allowed to be updated.

:::

### Args syntax {#mssql-create-update-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [UpdatePermission](/api-reference/syntax-defs.mdx#updatepermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## mssql_drop_update_permission {#mssql-drop-update-permission}

The `mssql_drop_update_permission` API is used to drop an existing
update permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_drop_update_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user"
    }
}
```

### Args syntax {#mssql-drop-update-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## mssql_create_delete_permission {#mssql-create-delete-permission}

A delete permission is used to restrict the rows that can be deleted.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_create_delete_permission",
    "args" : {
        "table" : "article",
        "source": "default",
        "role" : "user",
        "permission" : {
            "filter" : {
                "author_id" : "X-HASURA-USER-ID"
            }
        }
    }
}
```

This reads as follows:

"`delete` for the `user` role on the `article` table is allowed on rows
where `author_id` is the same as the request header `X-HASURA-USER-ID`
value."

### Args syntax {#mssql-create-delete-permission-syntax}

| Key        | Required | Schema                                                              | Description                                                   |
| ---------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
| table      | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)               | Name of the table                                             |
| role       | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)                 | Role                                                          |
| permission | true     | [DeletePermission](/api-reference/syntax-defs.mdx#deletepermission) | The permission definition                                     |
| comment    | false    | text                                                                | Comment                                                       |
| source     | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename)             | Name of the source database of the table (default: `default`) |

## mssql_drop_delete_permission {#mssql-drop-delete-permission}

The `mssql_drop_delete_permission` API is used to drop an existing
delete permission for a role on a table.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
    "type" : "mssql_drop_delete_permission",
    "args" : {
        "table" : "article",
        "role" : "user",
        "source": "default"
    }
}
```

### Args syntax {#mssql-drop-delete-permission-syntax}

| Key    | Required | Schema                                                  | Description                                                   |
| ------ | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table  | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role   | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | Role                                                          |
| source | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |

## mssql_set_permission_comment {#mssql-set-permission-comment}

`mssql_set_permission_comment` is used to set/update the comment on a permission. Setting the comment to `null` removes it.

An example:

```http
POST /v1/metadata HTTP/1.1
Content-Type: application/json
Authorization: Bearer <auth-token> # optional if cookie is set
X-Hasura-Role: admin

{
    "type": "mssql_set_permission_comment",
    "args": {
        "table": "article",
        "source": "default",
        "role": "user",
        "type" : "update",
        "comment" : "can only modify their own rows"
    }
}
```

### Args syntax {#mssql-set-permission-comment-syntax}

| Key     | Required | Schema                                                  | Description                                                   |
| ------- | -------- | ------------------------------------------------------- | ------------------------------------------------------------- |
| table   | true     | [TableName](/api-reference/syntax-defs.mdx#tablename)   | Name of the table                                             |
| role    | true     | [RoleName](/api-reference/syntax-defs.mdx#rolename)     | The role in the permission                                    |
| type    | true     | permission type (one of select/update/delete/insert)    | The type of the permission                                    |
| comment | false    | Text                                                    | Comment                                                       |
| source  | false    | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |
